package cn.com.nou.common;

import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.context.request.WebRequest;
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;

import javax.servlet.http.HttpServletResponse;
import javax.validation.ConstraintViolationException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 自定义逻辑异常类
 *
 * @author lixuefeng
 */
public class NouExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(NouExceptionHandler.class);

    @ExceptionHandler
    @ResponseBody
    public Map<String, Object> handler(Exception ex, HttpServletResponse response) {
        Map<String, Object> resultMap = Maps.newHashMap();
        if (ex instanceof NouException) {
            resultMap.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
            resultMap.put("message", ex.getMessage());
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return resultMap;
        } else if (ex instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException e = (MethodArgumentNotValidException) ex;
            List<ObjectError> errors = e.getBindingResult().getAllErrors();
            StringBuffer message = new StringBuffer();
            errors.forEach(item -> {
                message.append("\n").append(item.getDefaultMessage());
            });
            resultMap.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
            resultMap.put("message", message.length() > 0 ? message.substring(1) : message);
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return resultMap;
        } else if (ex instanceof ConstraintViolationException) {
            ConstraintViolationException ce = (ConstraintViolationException) ex;
            StringBuffer message = new StringBuffer();
            ce.getConstraintViolations().forEach(item -> {
                message.append("\n").append(item.getMessage());
            });
            resultMap.put("code", HttpStatus.INTERNAL_SERVER_ERROR.value());
            resultMap.put("message", message.length() > 0 ? message.substring(1) : message);
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return resultMap;
        } else {
            logger.error(ex.getMessage(), ex);
            resultMap.put("code", 501);
            resultMap.put("message", ex.getMessage());
            response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
            return resultMap;
        }
    }
}
